package cn.jg.framework.common.util;

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;

/**
 * @author fanfeveryahoo@gmail.com
 * @date 2019/11/26
 */
public class TimeUtils {

	private static DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
	private static DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

	private TimeUtils() {
	}

	/**
	 * formatDate
	 *
	 * @param date LocalDate
	 * @return str like yyyy-MM-dd
	 */
	public static String formatDate(LocalDate date) {
		return dateFormatter.format(date);
	}

	/**
	 * formatDate
	 *
	 * @param date Date
	 * @return str like yyyy-MM-dd
	 */
	public static String formatDate(Date date) {
		return dateFormatter.format(asLocalDate(date));
	}

	/**
	 * formatDateTime
	 *
	 * @param dateTime LocalDateTime
	 * @return str like yyyy-MM-dd HH:mm:ss
	 */
	public static String formatDateTime(LocalDateTime dateTime) {
		return dateTimeFormatter.format(dateTime);
	}

	/**
	 * formatDateTime
	 *
	 * @param date Date
	 * @return str like yyyy-MM-dd HH:mm:ss
	 */
	public static String formatDateTime(Date date) {
		return dateTimeFormatter.format(asLocalDateTime(date));
	}

	/**
	 * date to LocalDate
	 *
	 * @param date Date
	 * @return LocalDate
	 */
	public static LocalDate asLocalDate(Date date) {
		return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDate();
	}

	/**
	 * date to LocalDateTime
	 *
	 * @param date Date
	 * @return localDateTime
	 */
	public static LocalDateTime asLocalDateTime(Date date) {
		return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDateTime();
	}

	/**
	 * localDate to Date
	 *
	 * @param localDate LocalDate
	 * @return date
	 */
	public static Date asDate(LocalDate localDate) {
		return Date.from(localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
	}

	/**
	 * localDateTime to Date
	 *
	 * @param localDateTime LocalDateTime
	 * @return date
	 */
	public static Date asDate(LocalDateTime localDateTime) {
		return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
	}

	/**
	 * Epoch seconds to LocalDateTime
	 *
	 * @param seconds seconds
	 * @param zoneId  e.q. ZoneId.of("Asia/Shanghai")
	 * @return localDateTime
	 */
	public static LocalDateTime epochToTime(long seconds, ZoneId zoneId) {
		return LocalDateTime.ofInstant(Instant.ofEpochSecond(seconds), zoneId);
	}

	/**
	 * Epoch seconds to LocalDateTime
	 *
	 * @param seconds seconds
	 * @return localDateTime
	 */
	public static LocalDateTime epochToTime(long seconds) {
		return epochToTime(seconds, ZoneId.systemDefault());
	}

	/**
	 * LocalDateTime to Epoch seconds
	 *
	 * @param time   support mysql, elasticsearch, javaBean
	 * @param zoneId e.q. ZoneId.of("Asia/Shanghai")
	 * @return epoch second
	 */
	public static long timeToEpoch(LocalDateTime time, ZoneId zoneId) {
		return time.atZone(zoneId).toEpochSecond();
	}

	/**
	 * LocalDateTime to Epoch seconds
	 *
	 * @param time support mysql, elasticsearch, javaBean
	 * @return epoch second
	 */
	public static long timeToEpoch(LocalDateTime time) {
		return timeToEpoch(time, ZoneId.systemDefault());
	}

	/**
	 * LocalDateTime to Epoch milliseconds
	 *
	 * @param time   support mysql, elasticsearch, javaBean
	 * @param zoneId e.q. ZoneId.of("Asia/Shanghai")
	 * @return epoch millisecond
	 */
	public static long timeToEpochMilli(LocalDateTime time, ZoneId zoneId) {
		return time.atZone(zoneId).toInstant().toEpochMilli();
	}

	/**
	 * LocalDateTime to Epoch milliseconds
	 *
	 * @param time support mysql, elasticsearch, javaBean
	 * @return epoch millisecond
	 */
	public static long timeToEpochMilli(LocalDateTime time) {
		return timeToEpochMilli(time, ZoneId.systemDefault());
	}

	/**
	 * Epoch milliseconds to LocalDateTime
	 *
	 * @param milliseconds milliseconds
	 * @param zoneId       e.q. ZoneId.of("Asia/Shanghai")
	 * @return localDateTime
	 */
	public static LocalDateTime epochMilliToTime(long milliseconds, ZoneId zoneId) {
		return LocalDateTime.ofInstant(Instant.ofEpochMilli(milliseconds), zoneId);
	}

	/**
	 * Epoch milliseconds to LocalDateTime
	 *
	 * @param milliseconds milliseconds
	 * @return localDateTime
	 */
	public static LocalDateTime epochMilliToTime(long milliseconds) {
		return epochMilliToTime(milliseconds, ZoneId.systemDefault());
	}

}
